home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / SOURCE / MAIN.C < prev    next >
C/C++ Source or Header  |  1992-12-07  |  12KB  |  505 lines

  1. /* UNIX Moria Version 5.x
  2.    source/main.c: initialization, main() function and main loop
  3.    Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9.  
  10. /* Original copyright message follows. */
  11.  
  12. /* Moria Version 4.8    COPYRIGHT (c) Robert Alan Koeneke        */
  13. /*                                     */
  14. /*     I lovingly dedicate this game to hackers and adventurers     */
  15. /*     everywhere...                             */
  16. /*                                     */
  17. /*                                     */
  18. /*     Designer and Programmer : Robert Alan Koeneke             */
  19. /*                   University of Oklahoma         */
  20. /*                                     */
  21. /*     Assistant Programmers     : Jimmey Wayne Todd             */
  22. /*                   University of Oklahoma         */
  23. /*                                     */
  24. /*                   Gary D. McAdoo             */
  25. /*                   University of Oklahoma         */
  26. /*                                     */
  27. /*     UNIX Port         : James E. Wilson             */
  28. /*                   UC Berkeley                 */
  29. /*                   wilson@kithrup.com             */
  30. /*                                     */
  31. /*     MSDOS Port         : Don Kneller                 */
  32. /*                   1349 - 10th ave             */
  33. /*                   San Francisco, CA 94122         */
  34. /*                   kneller@cgl.ucsf.EDU             */
  35. /*                   ...ucbvax!ucsfcgl!kneller         */
  36. /*                   kneller@ucsf-cgl.BITNET         */
  37. /*                                     */
  38. /*     BRUCE Moria         : Christopher Stuart             */
  39. /*                   Monash University             */
  40. /*                   Melbourne, Victoria, AUSTRALIA     */
  41. /*                   cjs@moncsbruce.oz             */
  42. /*                                     */
  43. /*       Amiga Port              : Corey Gehman                          */
  44. /*                                 Clemson University                    */
  45. /*                                 cg377170@eng.clemson.edu              */
  46. /*                                     */
  47. /*     Version 5.5         : David Grabiner             */
  48. /*                   Harvard University             */
  49. /*                   grabiner@math.harvard.edu         */
  50. /*                                                                       */
  51. /*     Moria may be copied and modified freely as long as the above     */
  52. /*     credits are retained.    No one who-so-ever may sell or market     */
  53. /*     this software in any form without the expressed written consent */
  54. /*     of the author Robert Alan Koeneke.                 */
  55. /*                                     */
  56.  
  57. #ifdef __TURBOC__
  58. #include    <io.h>
  59. #include    <stdio.h>
  60. #include    <stdlib.h>
  61. #endif /* __TURBOC__ */
  62.  
  63. #include "config.h"
  64. #include "constant.h"
  65. #include "types.h"
  66. #include "externs.h"
  67.  
  68. #ifndef USG
  69. #include <sys/types.h>
  70. #include <sys/param.h>
  71. #endif
  72.  
  73. #ifdef USG
  74. #ifndef ATARIST_MWC
  75. #include <string.h>
  76. #else
  77. #include "string.h"
  78. #endif
  79. #else
  80. #include <strings.h>
  81. #endif
  82.  
  83. #include <ctype.h>
  84.  
  85. #ifdef Pyramid
  86. #include <sys/time.h>
  87. #else
  88. #include <time.h>
  89. #endif
  90.  
  91. #ifndef VMS
  92. #ifndef MAC
  93. #ifndef GEMDOS
  94. #ifndef AMIGA
  95. long time();
  96. #endif
  97. #endif
  98. char *getenv();
  99. #endif
  100. #endif
  101.  
  102. #ifndef MAC
  103. #ifndef AMIGA
  104. #ifdef USG
  105. #if !defined(MSDOS) && !defined(ATARIST_TC)
  106. unsigned short getuid(), getgid();
  107. #endif
  108. #else
  109. #ifndef SECURE
  110. #ifdef BSD4_3
  111. uid_t getuid(), getgid();
  112. #else  /* other BSD versions */
  113. int getuid(), getgid();
  114. #endif
  115. #endif
  116. #endif
  117. #endif
  118. #endif
  119.  
  120. #ifndef VMS
  121. #ifndef MAC
  122. #if defined(ultrix) || defined(USG)
  123. void perror();
  124. #endif
  125. #endif
  126. #endif
  127.  
  128. #ifndef VMS
  129. #ifndef MAC
  130. #ifdef USG
  131. void exit();
  132. #endif
  133. #endif
  134. #endif
  135.  
  136. /*
  137. #if defined(atarist) && defined(__GNUC__)
  138. long _stksize = 64*1024;
  139. #endif
  140. */
  141.  
  142. #ifdef ATARIST_MWC
  143. long _stksize = 18000;        /*(SAJ) for MWC    */
  144. #endif
  145.  
  146. #ifdef __TURBOC__
  147. unsigned _stklen = 0x3fff;    /* increase stack from 4K to 16K */
  148. #endif
  149.  
  150. #if defined(LINT_ARGS)
  151. static void char_inven_init(void);
  152. static void init_m_level(void);
  153. static void init_t_level(void);
  154. #if (COST_ADJ != 100)
  155. static void price_adjust(void);
  156. #endif
  157. #else
  158. static void char_inven_init();
  159. static void init_m_level();
  160. static void init_t_level();
  161. #if (COST_ADJ != 100)
  162. static void price_adjust();
  163. #endif
  164. #endif
  165.  
  166. /* Initialize, restore, and get the ball rolling.    -RAK-    */
  167. #ifdef MAC
  168. /* This is just a subroutine for the Mac version */
  169. /* only options passed in are -orn */
  170. /* save file name is never passed */
  171. int moria_main(argc, argv)
  172. int argc;
  173. char *argv[];
  174. #else
  175. int main(argc, argv)
  176. int argc;
  177. char *argv[];
  178. #endif
  179. {
  180.   int32u seed;
  181.   int generate;
  182.   int result;
  183. #ifndef MAC
  184.   char *p;
  185. #endif
  186.   int new_game = FALSE;
  187.   int force_rogue_like = FALSE;
  188.   int force_keys_to;
  189.  
  190.   /* default command set defined in config.h file */
  191.   rogue_like_commands = ROGUE_LIKE;
  192.  
  193. #ifdef SECURE
  194.   Authenticate();
  195. #endif
  196.  
  197. #ifdef MSDOS
  198.   msdos_init();        /* find out where everything is */
  199. #endif
  200.  
  201.   /* call this routine to grab a file pointer to the highscore file */
  202.   /* and prepare things to relinquish setuid privileges */
  203.   init_scorefile();
  204.  
  205. #ifndef SECURE
  206. #if !defined(MSDOS) && !defined(ATARIST_MWC) && !defined(MAC)
  207. #if !defined(AMIGA) && !defined(ATARIST_TC)
  208. #if !defined(atarist)
  209.   if (0 != setuid(getuid()))
  210.     {
  211.       perror("Can't set permissions correctly!  Setuid call failed.\n");
  212.       exit(0);
  213.     }
  214.   if (0 != setgid(getgid()))
  215.     {
  216.       perror("Can't set permissions correctly!  Setgid call failed.\n");
  217.       exit(0);
  218.     }
  219. #endif
  220. #endif
  221. #endif
  222. #endif
  223.  
  224.   /* use curses */
  225.   init_curses();
  226.  
  227. #ifdef VMS
  228.   /* Bizarre, but yes this really is needed to make moria work correctly
  229.      under VMS.  */
  230.   restore_screen ();
  231. #endif
  232.  
  233.   /* catch those nasty signals */
  234.   /* must come after init_curses as some of the signal handlers use curses */
  235.   init_signals();
  236.  
  237.   seed = 0; /* let wizard specify rng seed */
  238.   /* check for user interface option */
  239.   for (--argc, ++argv; argc > 0 && argv[0][0] == '-'; --argc, ++argv)
  240.     switch (argv[0][1])
  241.       {
  242.       case 'N':
  243.       case 'n': new_game = TRUE; break;
  244.       case 'O':
  245.       case 'o':
  246.     /* rogue_like_commands may be set in get_char(), so delay this
  247.        until after read savefile if any */
  248.     force_rogue_like = TRUE;
  249.     force_keys_to = FALSE;
  250.     break;
  251.       case 'R':
  252.       case 'r':
  253.     force_rogue_like = TRUE;
  254.     force_keys_to = TRUE;
  255.     break;
  256. #ifndef MAC
  257.       case 'S': display_scores(TRUE); exit_game();
  258.       case 's': display_scores(FALSE); exit_game();
  259.       case 'W':
  260.       case 'w':
  261.     to_be_wizard = TRUE;
  262.  
  263.     if (isdigit((int)argv[0][2]))
  264.       seed = atoi(&argv[0][2]);
  265.     break;
  266.       default: (void) printf("Usage: moria [-norsw] [savefile]\n");
  267.     exit_game();
  268. #endif
  269.       }
  270.  
  271. #ifndef MAC
  272.   /* Check operating hours            */
  273.   /* If not wizard  No_Control_Y           */
  274.   read_times();
  275. #endif
  276.  
  277.   /* Some necessary initializations        */
  278.   /* all made into constants or initialized in variables.c */
  279.  
  280. #if (COST_ADJ != 100)
  281.   price_adjust();
  282. #endif
  283.  
  284.   /* Grab a random seed from the clock        */
  285.   init_seeds(seed);
  286.  
  287.   /* Init monster and treasure levels for allocate */
  288.   init_m_level();
  289.   init_t_level();
  290.  
  291.   /* Init the store inventories            */
  292.   store_init();
  293.  
  294. #ifndef MAC
  295.   /* On Mac, if -n is passed, no savefile is used */
  296.   /* If -n is not passed, the calling routine will know savefile name,
  297.      hence, this code is not necessary */
  298.  
  299.   /* Auto-restart of saved file */
  300.   if (argv[0] != CNIL)
  301.     (void) strcpy (savefile, argv[0]);
  302.   else if ((p = getenv("MORIA_SAV")) != CNIL)
  303.     (void) strcpy(savefile, p);
  304.   else if ((p = getenv("HOME")) != CNIL)
  305. #if defined(ATARIST_MWC) || defined(ATARIST_TC)
  306.     (void) sprintf(savefile, "%s\\%s", p, MORIA_SAV);
  307. #else
  308. #ifdef VMS
  309.     (void) sprintf(savefile, "%s%s", p, MORIA_SAV);
  310. #else
  311.     (void) sprintf(savefile, "%s/%s", p, MORIA_SAV);
  312. #endif
  313. #endif
  314.   else
  315.     (void) strcpy(savefile, MORIA_SAV);
  316. #endif
  317.  
  318. /* This restoration of a saved character may get ONLY the monster memory. In
  319.    this case, get_char returns false. It may also resurrect a dead character
  320.    (if you are the wizard). In this case, it returns true, but also sets the
  321.    parameter "generate" to true, as it does not recover any cave details. */
  322.  
  323.   result = FALSE;
  324. #ifdef MAC
  325.   if ((new_game == FALSE) && get_char(&generate))
  326. #else
  327.   if ((new_game == FALSE) && !access(savefile, 0) && get_char(&generate))
  328. #endif
  329.     result = TRUE;
  330.  
  331.   /* enter wizard mode before showing the character display, but must wait
  332.      until after get_char in case it was just a resurrection */
  333.   if (to_be_wizard)
  334.     if (!enter_wiz_mode())
  335.       exit_game();
  336.  
  337.   if (result)
  338.     {
  339.       change_name();
  340.  
  341.       /* could be restoring a dead character after a signal or HANGUP */
  342.       if (py.misc.chp < 0)
  343.     death = TRUE;
  344.     }
  345.   else
  346.     {      /* Create character       */
  347.       create_character();
  348. #ifdef MAC
  349.       birth_date = time ((time_t *)0);
  350. #else
  351.       birth_date = time ((long *)0);
  352. #endif
  353.       char_inven_init();
  354.       py.flags.food = 7500;
  355.       py.flags.food_digested = 2;
  356.       if (class[py.misc.pclass].spell == MAGE)
  357.     {      /* Magic realm   */
  358.       clear_screen(); /* makes spell list easier to read */
  359.       calc_spells(A_INT);
  360.       calc_mana(A_INT);
  361.     }
  362.       else if (class[py.misc.pclass].spell == PRIEST)
  363.     {      /* Clerical realm*/
  364.       calc_spells(A_WIS);
  365.       clear_screen(); /* force out the 'learn prayer' message */
  366.       calc_mana(A_WIS);
  367.     }
  368.       /* prevent ^c quit from entering score into scoreboard,
  369.      and prevent signal from creating panic save until this point,
  370.      all info needed for save file is now valid */
  371.       character_generated = 1;
  372.       generate = TRUE;
  373.     }
  374.  
  375.   if (force_rogue_like)
  376.     rogue_like_commands = force_keys_to;
  377.  
  378.   magic_init();
  379.  
  380.   /* Begin the game                */
  381.   clear_screen();
  382.   prt_stat_block();
  383.   if (generate)
  384.     generate_cave();
  385.  
  386.   /* Loop till dead, or exit            */
  387.   while(!death)
  388.     {
  389.       dungeon();                  /* Dungeon logic */
  390.  
  391. #ifndef MAC
  392.       /* check for eof here, see inkey() in io.c */
  393.       /* eof can occur if the process gets a HANGUP signal */
  394.       if (eof_flag)
  395.     {
  396.       (void) strcpy(died_from, "(end of input: saved)");
  397.       if (!save_char())
  398.         {
  399.           (void) strcpy(died_from, "unexpected eof");
  400.         }
  401.       /* should not reach here, by if we do, this guarantees exit */
  402.       death = TRUE;
  403.     }
  404. #endif
  405.  
  406.       if (!death) generate_cave();           /* New level    */
  407.     }
  408.  
  409.   exit_game();        /* Character gets buried. */
  410.   /* should never reach here, but just in case */
  411.   return (0);
  412. }
  413.  
  414. /* Init players with some belongings            -RAK-    */
  415. static void char_inven_init()
  416. {
  417.   register int i, j;
  418.   inven_type inven_init;
  419.  
  420.   /* this is needed for bash to work right, it can't hurt anyway */
  421.   for (i = 0; i < INVEN_ARRAY_SIZE; i++)
  422.     invcopy(&inventory[i], OBJ_NOTHING);
  423.  
  424.   for (i = 0; i < 5; i++)
  425.     {
  426.       j = player_init[py.misc.pclass][i];
  427.       invcopy(&inven_init, j);
  428.       /* this makes it known2 and known1 */
  429.       store_bought(&inven_init);
  430.       /* must set this bit to display tohit/todam for stiletto */
  431.       if (inven_init.tval == TV_SWORD)
  432.     inven_init.ident |= ID_SHOW_HITDAM;
  433.       (void) inven_carry(&inven_init);
  434.     }
  435.  
  436.   /* wierd place for it, but why not? */
  437.   for (i = 0; i < 32; i++)
  438.     spell_order[i] = 99;
  439. }
  440.  
  441.  
  442. /* Initializes M_LEVEL array for use with PLACE_MONSTER    -RAK-    */
  443. static void init_m_level()
  444. {
  445.   register int i, k;
  446.  
  447.   for (i = 0; i <= MAX_MONS_LEVEL; i++)
  448.     m_level[i] = 0;
  449.  
  450.   k = MAX_CREATURES - WIN_MON_TOT;
  451.   for (i = 0; i < k; i++)
  452.     m_level[c_list[i].level]++;
  453.  
  454.   for (i = 1; i <= MAX_MONS_LEVEL; i++)
  455. #ifdef AMIGA  /* fix a stupid MANX Aztec C 5.0 bug again */
  456.     m_level[i] = m_level[i] + m_level[i-1];
  457. #else
  458.     m_level[i] += m_level[i-1];
  459. #endif
  460. }
  461.  
  462.  
  463. /* Initializes T_LEVEL array for use with PLACE_OBJECT    -RAK-    */
  464. static void init_t_level()
  465. {
  466.   register int i, l;
  467.   int tmp[MAX_OBJ_LEVEL+1];
  468.  
  469.   for (i = 0; i <= MAX_OBJ_LEVEL; i++)
  470.     t_level[i] = 0;
  471.   for (i = 0; i < MAX_DUNGEON_OBJ; i++)
  472.     t_level[object_list[i].level]++;
  473.   for (i = 1; i <= MAX_OBJ_LEVEL; i++)
  474. #ifdef AMIGA  /* fix a stupid MANX Aztec C 5.0 bug again */
  475.     t_level[i] = t_level[i] + t_level[i-1];
  476. #else
  477.     t_level[i] += t_level[i-1];
  478. #endif
  479.  
  480.   /* now produce an array with object indexes sorted by level, by using
  481.      the info in t_level, this is an O(n) sort! */
  482.   /* this is not a stable sort, but that does not matter */
  483.   for (i = 0; i <= MAX_OBJ_LEVEL; i++)
  484.     tmp[i] = 1;
  485.   for (i = 0; i < MAX_DUNGEON_OBJ; i++)
  486.     {
  487.       l = object_list[i].level;
  488.       sorted_objects[t_level[l] - tmp[l]] = i;
  489.       tmp[l]++;
  490.     }
  491. }
  492.  
  493.  
  494. #if (COST_ADJ != 100)
  495. /* Adjust prices of objects                -RAK-    */
  496. static void price_adjust()
  497. {
  498.   register int i;
  499.  
  500.   /* round half-way cases up */
  501.   for (i = 0; i < MAX_OBJECTS; i++)
  502.     object_list[i].cost = ((object_list[i].cost * COST_ADJ) + 50) / 100;
  503. }
  504. #endif
  505.